#pragma once
#include "eventloop.h"
#include "socket.h"
#include "channel.h"
#include "buffer.h"
#include<cstring>
#include<functional>

class Connection
{
private:
    std::shared_ptr<EventLoop> loop;
    std::shared_ptr<Socket> sock;
    Channel *channel;
    Buffer *readBuffer;
    Buffer *writeBuffer;
    std::function<void(std::shared_ptr<Socket>)> deleteConnectionCallback;
public:
    Connection(std::shared_ptr<Epoll> ep, std::shared_ptr<EventLoop> _loop, std::shared_ptr<Socket> _sock);
    ~Connection();
    void echo(int sockfd);
    void setDeleteConnectionCallback(std::function<void(std::shared_ptr<Socket>)>);
};

Connection::Connection(std::shared_ptr<Epoll> _ep, std::shared_ptr<EventLoop> _loop, std::shared_ptr<Socket> _sock): 
loop(_loop), sock(_sock){
    readBuffer = new Buffer();
    writeBuffer = new Buffer();
    std::function<void()> cb = std::bind(&Connection::echo, this, sock->getFd()); 
    channel = new Channel(_ep, sock->getFd(), EPOLLIN | EPOLLET, cb); //该连接的Channel
    channel->enableReading(); //打开读事件监听
}

Connection::~Connection()
{
}

void Connection::echo(int sockfd){
    char buf[1024];     //这个buf大小无所谓
    while(true){    //由于使用非阻塞IO，读取客户端buffer，一次读取buf大小数据，直到全部读取完毕
        bzero(&buf, sizeof(buf));
        ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
        if(bytes_read > 0){
            std::cout<<buf<<std::endl;
            readBuffer->append(buf, bytes_read);
            errif(write(sockfd, readBuffer->c_str(), readBuffer->size()) == -1, "socket write error");
        } else if(bytes_read == -1 && errno == EINTR){  //客户端正常中断、继续读取
            printf("continue reading");
            continue;
        } else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO，这个条件表示数据全部读取完毕
            printf("message from client fd %d: %s\n", sockfd, readBuffer->c_str());
            errif(write(sockfd, readBuffer->c_str(), readBuffer->size()) == -1, "socket write error");
            readBuffer->clear();
            break;
        } else if(bytes_read == 0){  //EOF，客户端断开连接
            printf("EOF, client fd %d disconnected\n", sockfd);
            deleteConnectionCallback(sock);
            break;
        }
    }
}

void Connection::setDeleteConnectionCallback(std::function<void(std::shared_ptr<Socket>)> cb) {
    deleteConnectionCallback = cb;
}